package com.ibix.shiro;

import com.ibix.domain.bean.StatelessToken;
import com.ibix.domain.dto.UserDTO;
import com.ibix.service.impl.AuthorizationService;
import com.ibix.util.JWT;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 项目名称：CaiHai
 * <br>类描述：
 * <br>创建人：htliu
 * <br>创建时间：2017/8/3 10:18
 * <br>修改人:
 * <br>修改时间：2017/8/3 10:18
 * <br>修改备注：
 * <br>@version
 */
public class CustomRealm extends AuthorizingRealm {
    @Resource
    private AuthorizationService authorizationService;
    @Resource
    private JWT jwt;

    //设置realm的名称
    @Override
    public boolean supports(AuthenticationToken token) {
        //仅支持StatelessToken类型的Token
        return token instanceof StatelessToken;
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        //从principals获取主身份信息
        //将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的goGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo)
        UserDTO user = (UserDTO) principals.getPrimaryPrincipal();
        //根据身份信息获取权限信息,
        //模拟从数据库中获取到的动态权限数据

        //查到权限数据，返回授权信息(包括上边的permissions)
        SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
        List<String> roles = authorizationService.listRoles(user.getPhone());
        List<String> permissions = roles.stream().flatMap(v -> authorizationService.listPermissions(v).stream()).collect(Collectors.toList());
        simpleAuthorizationInfo.addRoles(roles);
        //将上边查询到授权信息填充到simpleAuthorizationInfo对象中
        simpleAuthorizationInfo.addStringPermissions(permissions);
        return simpleAuthorizationInfo;
    }

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        //token是用户输入的
        String accessToken = token.getCredentials().toString();
        UserDTO user = jwt.unSign(accessToken, UserDTO.class);
        if (user == null || !token.getPrincipal().equals(user.getPhone())) {
            return null;
        }
        return new SimpleAuthenticationInfo(
                user, accessToken, this.getName());
    }

    //清除缓存
    public void clearCached() {
        PrincipalCollection principals = SecurityUtils.getSubject().getPrincipals();
        super.clearCache(principals);
    }
}
